<template>
  <div>
    <!-- 三级菜单组件 -->
    <el-tree
      :data="menus"
      :props="defaultProps"
      show-checkbox
      node-key="catId"
      :draggable="false"
      :allow-drop="allowDrop"
      :default-expanded-keys="expandedKey"
      highlight-current
      :filter-node-method="filterNode"
      @node-drop="handleDrop"
    >
      <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <el-button
            v-if="data.catLevel < 3"
            type="text"
            size="mini"
            @click.stop="() => append(data)"
          >新增分类</el-button>
          <el-button type="text" size="mini" @click.stop="() => edit(data)">修改分类</el-button>
          <el-button
            v-if="data.children.length == 0"
            type="text"
            size="mini"
            @click.stop="() => remove(node, data)"
          >删除分类</el-button>
        </span>
      </span>
    </el-tree>

    <el-dialog :title="dialogTitle" :visible.sync="dialogFormVisible" :close-on-click-modal="false">
      <el-form :model="category">
        <el-form-item label="分类名称" :label-width="formLabelWidth">
          <el-input v-model="category.name" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="图标" :label-width="formLabelWidth">
          <el-input v-model="category.icon" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="计量单位" :label-width="formLabelWidth">
          <el-input v-model="category.productUnit" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitData">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
// 这里可以导入其他文件(比如：组件，工具js，第三方插件js，json文件，图片文件等等
// 例如 import xxx from xxxPath;
export default {
  // import引入的组件需要注入到对象中才能使用
  components: {},
  props: {},
  data() {
    // 这里存放数据
    return {
      // 菜单数据
      menus: [],

      // 默认展开的菜单id
      expandedKey: [],

      defaultProps: {
        children: "children",
        label: "name"
      },

      // 对话框属性, 默认设置为false, 不显示
      dialogFormVisible: false,
      // 对话框标题
      dialogTitle: "",
      // 对话框类型, 新增(add), 修改(edit)
      dialogType: "",

      // 被拖动节点的总层级数
      maxLevel: 0,

      // 过滤文本
      filterText: "",

      // 菜单对象
      category: {
        name: "",
        parentCid: 0,
        catLevel: 0,
        showStatus: 1,
        sort: 0,
        catId: null,
        icon: "",
        productUnit: ""
      },
      formLabelWidth: "100px"
    };
  },
  // 计算属性-类似于data概念
  computed: {},
  // 生命周期-创建完成(可以访问当前this实例)
  created() {
    // 获取菜单数据
    this.getMenus();
  },
  // 生命周期-挂载完成(可以访问DOM元素)
  mounted() {},
  // 监控data中的数据变化
  watch: {
    
  },
  methods: {
    getMenus() {
      this.$http({
        url: this.$http.adornUrl("/product/category/list/tree"),
        method: "get"
      }).then(({ data }) => (this.menus = data.data));
    },

    // 点击新增分类, 弹出对话框
    append(data) {
      console.log("数据:", data);

      // 将对话框的提交数据方式设置为新增类型
      this.dialogType = "add";
      // 修改对话框标题
      this.dialogTitle = "新增分类";
      this.dialogFormVisible = true;
      // 清空修改留下的属性
      this.category.catId = null;
      this.category.name = "";
      this.category.icon = "";
      this.category.productUnit = "";
      this.category.parentCid = data.catId;
      this.category.catLevel = data.catLevel + 1;
    },

    // 增加新分类
    addCategory() {
      console.log("要提交的数据", this.category);
      this.$http({
        url: this.$http.adornUrl("/product/category/save"),
        method: "post",
        data: this.$http.adornParams(this.category, false)
      }).then(({ data }) => {
        // 弹窗提醒
        this.$message({
          type: "success",
          message: "菜单新增成功!"
        });

        // 关闭对话框
        this.dialogFormVisible = false;
        // 重新请求页面数据
        this.getMenus();
        // 设置默认展开的菜单
        this.expandedKey = [this.category.parentCid];
      });
    },

    // 点击修改分类的方法
    edit(data) {
      console.log("要修改的数据: ", data);
      // 将对话框的提交数据方式设置为修改类型
      this.dialogType = "edit";
      // 修改对话框标题
      this.dialogTitle = "修改分类";

      // 展示对话框
      this.dialogFormVisible = true;

      // 回显数据应发送请求, 获取最新数据
      this.$http({
        url: this.$http.adornUrl(`/product/category/info/${data.catId}`),
        method: "get"
      }).then(({ data }) => {
        // 请求成功
        console.log("查询到的数据: ", data);
        // 回显名字
        this.category.name = data.data.name;
        // 用于更新时传递
        this.category.catId = data.data.catId;
        // 用于更新数据后, 保持菜单展开状态
        this.category.parentCid = data.data.parentCid;
        // 回显图标
        this.category.icon = data.data.icon;
        // 回显计量单位
        this.category.productUnit = data.data.productUnit;
      });
    },

    // 修改分类
    editCategory(data) {
      // 因为修改分类, 只能修改name, icon, productUnit, 这些数据, 其他不能修改, 所以我们不能直接传递this.category
      // 后端程序会根据前端传输的对象, 如果属性没有被赋值, 则不修改数据, 所以要构造新的category对象

      // 解构出这些数据
      var { catId, name, icon, productUnit } = this.category;
      // 属性名和属性值一致时, 可简写
      var newCategory = { catId, name, icon, productUnit };
      this.$http({
        url: this.$http.adornUrl("/product/category/update"),
        method: "post",
        data: this.$http.adornParams(newCategory, false)
      }).then(({ data }) => {
        // 弹窗提醒
        this.$message({
          type: "success",
          message: "菜单修改成功!"
        });

        // 关闭对话框
        this.dialogFormVisible = false;
        // 重新请求页面数据
        this.getMenus();
        // 设置默认展开的菜单
        this.expandedKey = [this.category.parentCid];
      });
    },

    // 删除分类
    remove(node, data) {
      console.log("数据: ", data);
      console.log("节点: ", node);

      // 删除之前, 增加弹框提示
      this.$confirm(`是否删除【${data.name}】菜单?`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          // 调用删除接口
          var ids = [data.catId];
          this.$http({
            url: this.$http.adornUrl("/product/category/delete"),
            method: "post",
            data: this.$http.adornParams(ids, false)
          }).then(({ data }) => {
            // 弹窗提醒
            this.$message({
              type: "success",
              message: "菜单删除成功!"
            });

            // 重新刷新页面请求
            this.getMenus();

            // 设置默认展开的节点
            this.expandedKey = [node.parent.data.catId];
          });
        })
        .catch(() => {
          // 弹窗提醒
          this.$message({
            type: "info",
            message: "已取消删除"
          });
        });
    },

    // 提交数据
    submitData() {
      if (this.dialogType == "add") {
        this.addCategory();
      } else if (this.dialogType == "edit") {
        this.editCategory();
      }
    },

    // 判定目标节点能否被放置
    allowDrop(draggingNode, dropNode, type) {
      console.log("draggingNode: ", draggingNode);
      console.log("dropNode: ", dropNode);
      //1、被拖动的当前节点以及所在的父节点总层数不能大于3
      //1）、计算被拖动的当前节点总层数
      this.maxLevel = 0;
      this.countNodeLevels(draggingNode);
      console.log("maxLevel: ", this.maxLevel);

      // 节点深度
      let deep = 0;
      if (this.maxLevel == 0) {
        deep = 1;
      } else {
        deep = Math.abs(this.maxLevel - draggingNode.level) + 1;
      }
      console.log("被拖动节点的总层数是: ", deep);

      // 判断是否可以拖动该节点
      if (type == "inner") {
        return deep + dropNode.level <= 3;
      } else {
        return deep + dropNode.parent.level <= 3;
      }
    },

    //找到所有子节点，求出最大深度
    countNodeLevels(node) {
      // 判断节点是否有子节点
      if (node.childNodes != null && node.childNodes.length > 0) {
        for (let index = 0; index < node.childNodes.length; index++) {
          if (node.childNodes[index].level > this.maxLevel) {
            this.maxLevel = node.childNodes[index].level;
          }
          this.countNodeLevels(node.childNodes[index]);
        }
      }
    },

    // 拖动成功后执行的函数
    handleDrop(draggingNode, dropNode, dropType, ev) {
      console.log("tree drop: ", draggingNode, dropNode, dropType, ev);

      // 1. 获取当前拖拽节点的父节点的id
      let parentCid = 0;
      // 获取当前拖拽节点的兄弟节点
      let siblings = null;
      if (dropType == "before" || dropType == "after") {
        dropNode.parent.data.id == undefined ? 0 : dropNode.parent.data.catId;
        parentCid = dropNode.parent.data.id;
        siblings = dropNode.parent.childNodes;
      } else {
        parentCid = dropNode.data.catId;
        siblings = dropNode.childNodes;
      }

      // 2. 当前拖拽节点的最新数据
      for (let index = 0; index < siblings.length; index++) {
        const element = array[index];
        if ((siblings[index].data.catId = draggingNode.data.catId)) {
          catLevel = siblings[index].level;
        }
      }
    },

    // 过滤搜索
    filterNode(value, data) {
        console.log("value data: ", value, data);
      }
  },
  // 生命周期-创建之前
  beforeCreate() {},
  // 生命周期-挂载之前
  beforeMount() {},
  // 生命周期-更新之前
  beforeUpdate() {},
  // 生命周期-更新之后
  updated() {},
  // 生命周期-销毁之前
  beforeDestroy() {},
  // 生命周期-销毁完成
  destroyed() {},
  // 如果页面有keep-alive缓存功能，这个函数会触发
  activated() {}
};
</script>

<style scoped>
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
</style>
